package org.nobject.common.image;

import java.awt.Color;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.Raster;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.net.URLConnection;

import javax.imageio.ImageIO;

/**
 * 图像工具类
 * 
 * @author benson
 * @version 1.0
 */
public class ImageUtils {

	/**
	 * 截取图像_种类_居中截取
	 */
	public final static int SUBIMG_TYPE_CENTER = 0;

	/**
	 * 截取图片-定比
	 * 
	 * @param srcImg
	 *            源图片
	 * @param width
	 *            宽度
	 * @param height
	 *            高度
	 * @param type
	 *            截取类型
	 * @see #SUBIMG_TYPE_CENTER
	 * @return <code>BufferedImage</code>
	 */
	public static BufferedImage subImgInScale(BufferedImage srcImg, int width, int height, int type) {
		int sw = srcImg.getWidth();
		int sh = srcImg.getHeight();
		double rateW = ((double) sw) / (double) width;
		double rateH = ((double) sh) / (double) height;

		int x = 0, y = 0;

		int nw = sw;
		int nh = sh;

		if (type == SUBIMG_TYPE_CENTER) {
			if (rateW != rateH) {
				if (rateW > rateH) {// w太长
					nw = (int) (width * rateH);
					x = (int) (sw - nw) / 2;
				} else {// h太长
					nh = (int) (height * rateW);
					y = (int) (sh - nh) / 2;
				}
			}
		}
		return srcImg.getSubimage(x, y, nw, nh);
	}

	/**
	 * 缩放图片
	 * 
	 * @param srcImg
	 *            原图片
	 * @param width
	 *            宽度
	 * @param height
	 *            高度
	 * @param proportion
	 *            是否等比例
	 * @return <code>BufferedImage</code>
	 */
	public static BufferedImage zoomImg(BufferedImage srcImg, int width, int height, boolean proportion) {
		return zoomImg(srcImg, width, height, proportion, false);
	}

	/**
	 * zoomImg EXP: File f=new File("C:/2.jpg");
	 * ImageIO.write(ImageUtils.zoomImg(ImageIO.read(f), 120, 120,
	 * true),"jpg",new File("C:/1_z.jpg"));
	 * 
	 * @param srcImg
	 * @param width
	 * @param height
	 * @param proportion
	 * @param argb
	 *            是否用透明处理
	 */
	public static BufferedImage zoomImg(BufferedImage srcImg, int width, int height, boolean proportion, boolean argb) {
		int sw = srcImg.getWidth();
		int sh = srcImg.getHeight();

		int nw = sw;
		int nh = sh;
		if (width > 0 && height > 0 && sw > 0 && sh > 0) {
			if (proportion == true) {// 等比例缩放
				double rate1 = ((double) sw) / (double) width;
				double rate2 = ((double) sh) / (double) height;
				double rate = rate1 > rate2 ? rate1 : rate2;
				nw = (int) (sw / rate);
				nh = (int) (sh / rate);
			} else {
				nw = width;
				nh = height;
			}
		}

		BufferedImage newImg = new BufferedImage(nw, nh, argb ? BufferedImage.TYPE_INT_ARGB : BufferedImage.TYPE_INT_RGB);// 透明处理时有BUG
		newImg.getGraphics().drawImage(srcImg.getScaledInstance(nw, nh, Image.SCALE_SMOOTH), 0, 0, null);
		srcImg = newImg.getSubimage(0, 0, nw, nh);
		return srcImg;
	}

	public static void convertPicture(File sImgFile, String dImgPath, int width, int height) {
		if (sImgFile.exists()) {
			try {
				BufferedImage sImage = ImageIO.read(sImgFile);
				sImage = ImageUtils.subImgInScale(sImage, width, height, ImageUtils.SUBIMG_TYPE_CENTER);
				sImage = ImageUtils.zoomImg(sImage, width, height, false);
				// sImage=ImageUtils.toJPEG(sImage);
				ImageIO.write(sImage, "JPEG", new File(dImgPath));
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

	/**
	 * 获取融合透明图片的RGB
	 * 
	 * @param img1
	 *            上层图片
	 * @param img2
	 *            下层图片
	 * @param x
	 *            横坐标
	 * @param y
	 *            纵坐标
	 */
	public static int getCpzTransImageRGB(BufferedImage img1, BufferedImage img2, int x, int y) {
		int r1 = 0, g1 = 0, b1 = 0, r2 = 0, g2 = 0, b2 = 0, a1, a2;
		Object data1 = img1.getRaster().getDataElements(x, y, null);
		Object data2 = img2.getRaster().getDataElements(x, y, null);
		r1 = img1.getColorModel().getRed(data1);
		b1 = img1.getColorModel().getBlue(data1);
		g1 = img1.getColorModel().getGreen(data1);
		a1 = img1.getColorModel().getAlpha(data1);

		r2 = img2.getColorModel().getRed(data2);
		b2 = img2.getColorModel().getBlue(data2);
		g2 = img2.getColorModel().getGreen(data2);
		a2 = img2.getColorModel().getAlpha(data2);
		double alp1 = a1 / 255d;
		double alp2 = a2 / 255d;
		int R = Double.valueOf((r1 * alp1 * (1d - alp2) + r2 * alp2) / (alp1 + alp2 - alp1 * alp2)).intValue();
		int G = Double.valueOf((g1 * alp1 * (1d - alp2) + g2 * alp2) / (alp1 + alp2 - alp1 * alp2)).intValue();
		int B = Double.valueOf((b1 * alp1 * (1d - alp2) + b2 * alp2) / (alp1 + alp2 - alp1 * alp2)).intValue();

		return ((Double.valueOf((alp1 + alp2 - (alp1 * alp2)) * 255).intValue()) << 24) | (new Color(R, G, B).getRGB() & 0x00ffffff);
	}

	/** composeShell */
	public static BufferedImage composeShell(BufferedImage sourceImage, BufferedImage shellImage, int mixScal, int w, int h) {
		if (w == -1)
			w = shellImage.getWidth();
		if (h == -1)
			h = shellImage.getHeight();
		if (shellImage.getWidth() * h != shellImage.getHeight() * w)
			shellImage = ImageUtils.subImgInScale(shellImage, w, h, ImageUtils.SUBIMG_TYPE_CENTER);
		if (shellImage.getWidth() != w || shellImage.getHeight() != h)
			shellImage = ImageUtils.zoomImg(shellImage, w, h, true);

		if (sourceImage.getWidth() * h != sourceImage.getHeight() * w)
			sourceImage = ImageUtils.subImgInScale(sourceImage, w, h, ImageUtils.SUBIMG_TYPE_CENTER);
		if (sourceImage.getWidth() != w || sourceImage.getHeight() != h)
			sourceImage = ImageUtils.zoomImg(sourceImage, w, h, true);
		Raster rasterSrc = shellImage.getRaster();
		ColorModel cm = shellImage.getColorModel();
		BufferedImage layerImage = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
		int wc = w / 2, hc = h / 2;
		boolean lineEmpty = false;

		for (int j = hc; j < h; j++) {
			int a = -1, b = -1;

			if (lineEmpty) {
				for (int i = w - 1; i >= 0; i--)
					layerImage.setRGB(i, j, shellImage.getRGB(i, j));
				continue;
			}

			for (int i = wc; i >= 0; i--) {
				if (a < 0) {
					if (cm.getAlpha(rasterSrc.getDataElements(i, j, null)) > mixScal)
						a = i;
					layerImage.setRGB(i, j, ImageUtils.getCpzTransImageRGB(sourceImage, shellImage, i, j));
				} else
					layerImage.setRGB(i, j, shellImage.getRGB(i, j));
			}

			for (int i = wc; i < w; i++) {
				if (b < 0) {
					if (cm.getAlpha(rasterSrc.getDataElements(i, j, null)) > mixScal)
						b = i;
					layerImage.setRGB(i, j, ImageUtils.getCpzTransImageRGB(sourceImage, shellImage, i, j));
				} else
					layerImage.setRGB(i, j, shellImage.getRGB(i, j));
			}

			if (a == -1 && b == -1) {
				lineEmpty = true;
				for (int i = w - 1; i >= 0; i--)
					layerImage.setRGB(i, j, shellImage.getRGB(i, j));
			} else if (a == -1)
				for (int i = wc; i >= 0; i--)
					layerImage.setRGB(i, j, shellImage.getRGB(i, j));
			else if (b == -1)
				for (int i = wc; i < w; i++)
					layerImage.setRGB(i, j, shellImage.getRGB(i, j));

		}

		lineEmpty = false;
		for (int j = hc; j >= 0; j--) {
			int a = -1, b = -1;
			if (lineEmpty) {
				for (int i = w - 1; i >= 0; i--)
					layerImage.setRGB(i, j, shellImage.getRGB(i, j));
				continue;
			}

			for (int i = wc; i >= 0; i--) {
				if (a < 0) {
					if (cm.getAlpha(rasterSrc.getDataElements(i, j, null)) > mixScal)
						a = i;
					layerImage.setRGB(i, j, ImageUtils.getCpzTransImageRGB(sourceImage, shellImage, i, j));
				} else
					layerImage.setRGB(i, j, shellImage.getRGB(i, j));
			}

			for (int i = wc; i < w; i++) {
				if (b < 0) {
					if (cm.getAlpha(rasterSrc.getDataElements(i, j, null)) > mixScal)
						b = i;
					layerImage.setRGB(i, j, ImageUtils.getCpzTransImageRGB(sourceImage, shellImage, i, j));
				} else
					layerImage.setRGB(i, j, shellImage.getRGB(i, j));
			}

			if (a == -1 && b == -1) {
				lineEmpty = true;
				for (int i = w - 1; i >= 0; i--)
					layerImage.setRGB(i, j, shellImage.getRGB(i, j));
			} else if (a == -1)
				for (int i = wc; i >= 0; i--)
					layerImage.setRGB(i, j, shellImage.getRGB(i, j));
			else if (b == -1)
				for (int i = wc; i < w; i++)
					layerImage.setRGB(i, j, shellImage.getRGB(i, j));
		}
		return layerImage;
	}

	/**
	 * 合并Shell
	 * 
	 * @param sourceImage
	 *            原图片
	 * @param shellImage
	 *            客图片
	 * @param mixScal
	 *            混合范围
	 */
	public static BufferedImage composeShell(BufferedImage sourceImage, BufferedImage shellImage, int mixScal) {
		int w = shellImage.getWidth();
		int h = shellImage.getHeight();
		return composeShell(sourceImage, shellImage, mixScal, w, h);
	}

	/**
	 * 切割Shell
	 * 
	 * @param sourceImage
	 *            原图片
	 * @param shellImage
	 *            客图片
	 * @param mixScal
	 *            混合范围
	 */
	public static BufferedImage cuteShell(BufferedImage sourceImage, BufferedImage shellImage, int mixScal) {
		int w = shellImage.getWidth();
		int h = shellImage.getHeight();
		return cuteShell(sourceImage, shellImage, mixScal, w, h);
	}

	/**
	 * cuteShell EXP: File sf=new File("D:/3.png"); File nf=new
	 * File("D:/1.jpg"); File f=new File("C:/2.jpg");
	 * ImageIO.write(ImageUtils.cuteShell(ImageIO.read(f),
	 * ImageIO.read(sf),15,50,50), "png", nf);
	 * 
	 * @param sourceImage
	 * @param shellImage
	 * @param mixScal
	 * @param w
	 * @param h
	 * @return
	 */
	public static BufferedImage cuteShell(BufferedImage sourceImage, BufferedImage shellImage, int mixScal, int w, int h) {
		if (w == -1)
			w = shellImage.getWidth();
		if (h == -1)
			h = shellImage.getHeight();
		if (shellImage.getWidth() * h != shellImage.getHeight() * w)
			shellImage = ImageUtils.subImgInScale(shellImage, w, h, ImageUtils.SUBIMG_TYPE_CENTER);
		if (shellImage.getWidth() != w || shellImage.getHeight() != h)
			shellImage = ImageUtils.zoomImg(shellImage, w, h, true);

		if (sourceImage.getWidth() * h != sourceImage.getHeight() * w)
			sourceImage = ImageUtils.subImgInScale(sourceImage, w, h, ImageUtils.SUBIMG_TYPE_CENTER);
		if (sourceImage.getWidth() != w || sourceImage.getHeight() != h)
			sourceImage = ImageUtils.zoomImg(sourceImage, w, h, true);
		Raster rasterSrc = shellImage.getRaster();
		ColorModel cm = shellImage.getColorModel();
		BufferedImage layerImage = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
		int wc = w / 2, hc = h / 2;
		boolean lineEmpty = false;

		for (int j = hc; j < h; j++) {
			int a = -1, b = -1;

			if (lineEmpty) {
				for (int i = w - 1; i >= 0; i--)
					layerImage.setRGB(i, j, shellImage.getRGB(i, j));
				continue;
			}

			for (int i = wc; i >= 0; i--) {
				if (cm.getAlpha(rasterSrc.getDataElements(i, j, null)) >= mixScal) {
					a = i;
					break;
				}
				layerImage.setRGB(i, j, ImageUtils.getCpzTransImageRGB(sourceImage, shellImage, i, j));
			}

			for (int i = wc; i < w; i++) {
				if (cm.getAlpha(rasterSrc.getDataElements(i, j, null)) >= mixScal) {
					b = i;
					break;
				}
				layerImage.setRGB(i, j, ImageUtils.getCpzTransImageRGB(sourceImage, shellImage, i, j));
			}

			if (a == -1 && b == -1) {
				lineEmpty = true;
				for (int i = w - 1; i >= 0; i--)
					layerImage.setRGB(i, j, shellImage.getRGB(i, j));
			} else if (a == -1)
				for (int i = wc; i >= 0; i--)
					layerImage.setRGB(i, j, shellImage.getRGB(i, j));
			else if (b == -1)
				for (int i = wc; i < w; i++)
					layerImage.setRGB(i, j, shellImage.getRGB(i, j));
		}

		lineEmpty = false;
		for (int j = hc; j >= 0; j--) {
			int a = -1, b = -1;
			if (lineEmpty) {
				for (int i = w - 1; i >= 0; i--)
					layerImage.setRGB(i, j, shellImage.getRGB(i, j));
				continue;
			}

			for (int i = wc; i >= 0; i--) {
				if (cm.getAlpha(rasterSrc.getDataElements(i, j, null)) >= mixScal) {
					a = i;
					break;
				}
				layerImage.setRGB(i, j, ImageUtils.getCpzTransImageRGB(sourceImage, shellImage, i, j));
			}

			for (int i = wc; i < w; i++) {
				if (cm.getAlpha(rasterSrc.getDataElements(i, j, null)) >= mixScal) {
					b = i;
					break;
				}
				layerImage.setRGB(i, j, ImageUtils.getCpzTransImageRGB(sourceImage, shellImage, i, j));
			}

			if (a == -1 && b == -1) {
				lineEmpty = true;
				for (int i = w - 1; i >= 0; i--)
					layerImage.setRGB(i, j, shellImage.getRGB(i, j));
			} else if (a == -1)
				for (int i = wc; i >= 0; i--)
					layerImage.setRGB(i, j, shellImage.getRGB(i, j));
			else if (b == -1)
				for (int i = wc; i < w; i++)
					layerImage.setRGB(i, j, shellImage.getRGB(i, j));
		}
		return layerImage;
	}

	/** 
	 * getImgFromUrl
	 * @param url
	 * @param savepath
	 */
	public static BufferedImage getImageFromUrl(String url) {
		try {
			URLConnection connection = new URL(url).openConnection();
			connection.setDoOutput(true);
			//connection.setRequestProperty("referer", u); // 通过这个http头的伪装来反盗链
			return ImageIO.read(connection.getInputStream());
		} catch (IOException e) {
			System.err.println(url);
			throw new RuntimeException(e);
		}
	}
}
